/*
 * ProbabilityCombinationVectorHistoryComponent.java
 *
 * Created on 19 de Julho de 2011, 13:53
 */

package intopo.demonstrator.partnerselection.gui;

import intopo.demonstrator.partnerselection.Parameters;
import intopo.demonstrator.partnerselection.State;

import java.awt.Color;
import java.util.Vector;
/**
 * A component that displays the history of the probability and combination vectors.
 *
 * @author  pedro
 */
public class ProbabilityCombinationVectorHistoryComponent
	extends util.gui.Plot2D
{
//	private Vector<State> history;

	/** Creates new form BeanForm */
	public ProbabilityCombinationVectorHistoryComponent ()
	{
//		this.history = new Vector<State> ();
//		this.history.add (new State (MonteCarloForm.parameters));
		setYRange (0, DataModel.parameters.getMaxProbability ());
		setTitle ("Probability and Combination Vectors");
		setXLabel ("Time");
		setYLabel ("Probability");
		setXRange (0, getWidth () / 2);
		for (int i = DataModel.parameters.getPoolSize () - 1; i >= 0; i--) {
			addData (new Data (i, true));
			addData (new Data (i, false));
		}
	}
	void parametersChanged ()
	{
		adjustXRange ();
		setYRange (0, DataModel.parameters.getMaxProbability ());
		setYTics (0, 2, DataModel.parameters.getMaxProbability ());
		this.clearData ();
		for (int i = DataModel.parameters.getPoolSize () - 1; i >= 0; i--) {
			this.addData (new Data (i, true));
			this.addData (new Data (i, false));
		}
		this.repaint ();
	}
	void newTransition ()
	{
		adjustXRange ();
		this.repaint ();
	}
	/**
	 * Adjusts the x range in order to show the last states in the history.
	 */
	final protected void adjustXRange ()
	{
		int space = (getWidth () - margin.left - margin.right + 1) / 5;
		if (space > DataModel.history.size ()) {
			setXRange (0, space);
			setXTics (0, 20, space);
		}
		else {
			setXRange (DataModel.history.size () - space, DataModel.history.size ());
			setXTics (DataModel.history.size () - space, 20, DataModel.history.size ());
		}
	}
	
	private class Data
		extends AbstractData
	{
		final private int slot;
		final private boolean acceptable;
		/**
		 * Time when an acceptable combination was selected to slot {@code slot}.
		 */
		transient private int timeAcceptableEntered;
		Data (int slot, boolean acceptable)
		{
			super (null, acceptable ? Color.GREEN : Color.RED, null, false, true, false);
			this.slot = slot;
			this.acceptable = acceptable;
			this.timeAcceptableEntered = -1;
		}
		public int size ()
		{
			if (timeAcceptableEntered == -1 && !calculateTimeAcceptableEntered ()) {
//				int min = 0;
//				int max = history.size () - 1;
//				while (min < max) {
//					int middle = (max + min) / 2;
//					if (!history.get (middle).isAcceptable (slot)
//						&& history.get (middle + 1).isAcceptable (slot)) {
//						if (acceptable) {
//							timeAcceptableEntered = history.size () - middle - 1;
//						}
//						else {
//							timeAcceptableEntered = middle + 1;
//						}
//						return timeAcceptableEntered;
//					}
//					else if (history.get (middle).isAcceptable (slot)) {
//						max = middle - 1;
//					}
//					else {
//						min = middle + 1;
//					}
//				}
				if (acceptable) {
					return -1;
				}
				else {
					return DataModel.history.size ();
				}
			}
			else {
				if (acceptable) {
					return DataModel.history.size () - timeAcceptableEntered;
				}
				else {
					return timeAcceptableEntered + 1;
				}
			}
		}
		private boolean calculateTimeAcceptableEntered ()
		{
			int min = 0;
			int max = DataModel.history.size () - 1;
			while (min < max) {
				int middle = (max + min) / 2;
				if (!DataModel.history.get (middle).isAcceptable (slot)
					&& DataModel.history.get (middle + 1).isAcceptable (slot)) {
					timeAcceptableEntered = middle + 1;
					return true;
				}
				else if (DataModel.history.get (middle).isAcceptable (slot)) {
					max = middle - 1;
				}
				else {
					min = middle + 1;
				}
			}
			return false;
		}
		public double x (int index)
		{
			if (acceptable) {
				return timeAcceptableEntered + index;
			}
			else {
				return index;
			}
		}
		public double y (int index)
		{
			if (acceptable) {
				return DataModel.history.get (timeAcceptableEntered + index).getRawProbability (slot);
			}
			else {
				return DataModel.history.get (index).getRawProbability (slot);
			}
		}
	}
	/** This method is called from within the constructor to
	 * initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is
	 * always regenerated by the Form Editor.
	 */
   // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
   private void initComponents() {

   }// </editor-fold>//GEN-END:initComponents
	
	
   // Variables declaration - do not modify//GEN-BEGIN:variables
   // End of variables declaration//GEN-END:variables
	
}
